package com.kehutong.charge.service.impl;

import com.kehutong.charge.dao.ReceiptOrdersDao;
import com.kehutong.charge.vo.ReceiptOrdersExcelVO;
import com.kehutong.charge.entity.*;
import com.kehutong.charge.service.ReceiptOrdersService;
import com.kehutong.charge.util.PdfTableUtil;
import com.kehutong.charge.util.PdfUtil;
import com.kehutong.charge.util.enums.BillPaidStates;
import com.kehutong.charge.util.enums.EnableStateEnum;
import com.kehutong.common.DeptService;
import com.kehutong.common.DoveClient;
import com.kehutong.common.dto.DeptDTO;
import com.kehutong.common.errcode.Assert;
import com.kehutong.common.excel.tool.ExcelTool;
import com.kehutong.common.urlconfig.FileUrlConfig;
import com.kehutong.common.util.ListUtils;
import com.kehutong.common.util.Token;
import org.coraframework.converter.util.StringUtil;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.http.result.Result;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.jdbc.execute.Condition;
import org.coraframework.orm.jdbc.execute.QueryCondition;
import org.coraframework.orm.jdbc.execute.entity.FindPage;
import org.coraframework.util.Objects;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: kht
 * @description: ReceiptOrdersServiceImpl
 * @author: jian Ye
 * @create: 2021/8/3
 **/
public class ReceiptOrdersServiceImpl implements ReceiptOrdersService {

    private static final Logger logger = LoggerFactory.getLogger(ReceiptOrdersServiceImpl.class);

    @Inject
    private JdbcSession jdbcSession;
    @Inject
    DeptService deptService;
    @Inject
    private DoveClient doveClient;
    @Inject
    private FileUrlConfig fileUrlConfig;
    @Inject
    private ReceiptOrdersDao receiptOrdersDao;
    @Inject
    private ExcelTool excelTool;



    @Override
    public Page<ReceiptOrders> findPage(JSONObject jsonObject) {
        FindPage<ReceiptOrders> find = jdbcSession.findPage(ReceiptOrders.class)
                .eq("deleted", false)
                .eq(jsonObject,"status")
                .eq(jsonObject,"communityNo")
                .like(jsonObject,"receiptNo")
                .like(jsonObject,"communityList")
                .like(jsonObject,"createTime");
        //添加选中导出条件
        JSONArray exportIdList = jsonObject.getJSONArray("exportIdList");
        if(!Objects.isEmpty(exportIdList)){
            find.in("receiptNo",exportIdList);
        }
        find.order("createTime", "desc");

        return find.page(jsonObject).exe();
    }


    @Override
    public void pageExport(HttpServletRequest req, HttpServletResponse resp, JSONObject jsonObject) {
        jsonObject.put("pageNo", 1);
        jsonObject.put("pageSize", Short.MAX_VALUE);
        List<ReceiptOrders> list = findPage(jsonObject).getList();
        Assert.notEmpty(list,"导出失败！没有找到相关的收据列表数据.");
        List<ReceiptOrdersExcelVO> dtoList = ListUtils.copyBeanList(list, ReceiptOrdersExcelVO::new);
        excelTool.excelDownload(req,resp,dtoList,"收据列表导出");
    }


    @Override
    public List<ReceiptOrders> findList(JSONObject jsonObject) {
        List<ReceiptOrders> receiptList = jdbcSession.findArray(ReceiptOrders.class)
                .eq("deleted", false)
                .eq("status",true)
                .order("createTime", "desc")
                .exe();
        return receiptList;
    }


    @Override
    public List<ReceiptOrders> findListByHouseNo(String houseNo) {
        List<ReceiptOrders> receiptList = jdbcSession.findArray(ReceiptOrders.class)
                .eq("deleted", false)
                .eq("houseBillNo",houseNo)
                .order("createTime","desc")
                .exe();
        return receiptList;
    }



    @Override
    public Object save(ReceiptOrders receiptOrders) throws Exception {
        return jdbcSession.insert(receiptOrders);
    }


    @Override
    public Object findOrderReceipt(JSONObject jsonObject) {
        ReceiptOrders receiptOrders = jdbcSession.findOne(ReceiptOrders.class)
                .eq(jsonObject,"houseBillNo")
                .eq("EnableStat", EnableStateEnum.UNUSED.getId()).exe();

        if(null == receiptOrders){
            return Result.error(1232,"没有找到对应的数据！");
        }
        return receiptOrders;
    }

    @Override
    public Object save(ReceiptOrders entity, Token token)  throws Exception {
        List<String> departList = token.getDepartments();
        if(null == departList || departList.size() == 0){
            logger.error("用户{}数据异常，部门为空！",token.getUsername());
        }
        DeptDTO deptDTO = deptService.getDept(departList.get(0));
        entity.setDepartmentNo(deptDTO.getDepartmentNo());
        entity.setDepartmentNos(deptDTO.getDepartmentNos());
        entity.setDepartmentName(deptDTO.getDepartmentName());
        return save(entity);
    }

    @Override
    public Object savePdf(ChargeBills receiptOrder, String companyNo) throws Exception {
        logger.info("手动生成PDF文件！小区编号：{}",receiptOrder.getCommunityNo());

        ReceiptManages receiptManage;
        try {
            //1、查询电子签章,判断是否有配置收据模板及公章
            receiptManage = jdbcSession.findOne(ReceiptManages.class)
                    .like("communityList", receiptOrder.getCommunityNo())
                    .eq("status", true).exe();

            if (null == receiptManage) {
                logger.error("{}小区未设置收据模板！", receiptOrder.getCommunityNo());
                return Result.error(0, "请先去设置或开启收据模板！");
            }
        }catch (Exception e){
            return Result.error(0, "票据模板设置不合理，同一个小区只能配置一个模板！");
        }

        //2、查询账单缴费状态
        ChargeBills chargeBill = jdbcSession.findById(ChargeBills.class,receiptOrder.getId());

        if(chargeBill.getPaidState().equals(BillPaidStates.UNPAID)){
            logger.error("{}未缴费，不能生成收据！",receiptOrder.getCommunityNo());
            return Result.error(0,  "未缴费不能生成收据！");
        }

        //3、查询账单数据
        Map<String,Object> mapParam = new LinkedHashMap<String,Object>();
        mapParam.put("company", receiptManage.getReceiptTitleName());
        mapParam.put("community",chargeBill.getCommunityName());
        String realName = ""; //房屋客人名称
        if(StringUtil.isEmpty(chargeBill.getPayerName())){
            realName =  getOwnerName(companyNo,chargeBill.getHouseNo());
        }else{
            realName = chargeBill.getPayerName();
        }
        mapParam.put("realName",realName);  //房东姓名
        // 显示： 12栋-1801
        StringBuffer houseInfo = new StringBuffer();
        houseInfo.append(chargeBill.getBuildingName()).append("-");
        if(StringUtil.isNotBlank(chargeBill.getUnitName())){
            houseInfo.append(chargeBill.getUnitName()).append("-");
        }
        if(StringUtil.isNotBlank(chargeBill.getFloorName())) {
            houseInfo.append(chargeBill.getFloorName());
        }
        houseInfo.append(chargeBill.getHouseName());
        mapParam.put("houseInfo",houseInfo);  //房号
        mapParam.put("datePay",chargeBill.getPaidAt());
        String receiptNo = PdfTableUtil.generateNumber("SJ");
        mapParam.put("receiptNO","NO."+receiptNo);
        //上传的签章图片
        String fileImg = fileUrlConfig.getFile(receiptManage.getSealImgId());
        mapParam.put("sealFile",fileImg);
        mapParam.put("type","receipt");
        mapParam.put("totalAmount",chargeBill.getTotal());
        mapParam.put("content",chargeBill.getBillDateFrom() +"至"+chargeBill.getBillDateTo());
        mapParam.put("payMethod",receiptOrder.getPayMethod().getDesc());

        //查询账单项
        List<ChargeBillItems> billItems = jdbcSession.findArray(ChargeBillItems.class).eq("billNo", chargeBill.getId()).exe();
        mapParam.put("dataList",billItems);

        //4、生成PDF文件
        PdfUtil pdfUtil = new PdfUtil();
        byte[] pdf = pdfUtil.execute(mapParam);

        String pdfName = receiptNo+".pdf";
        File file = new File(pdfName);

        FileOutputStream outputFileStream = new FileOutputStream(file);
        outputFileStream.write(pdf);
        outputFileStream.close();

        //保存收据单数据
        ReceiptOrders receipt =  Pool.newInstance(ReceiptOrders.class);
        receipt.setReceiptNo(receiptNo); //生成自定义编号
        receipt.setPayOrderNo(chargeBill.getId());
        JSONObject jsonObject =  fileUrlConfig.sendFile(file, http->{ });
        String fileId = jsonObject.getJSONObject("data").getString("id");
        receipt.setFileId(fileId);
        receipt.setHouseInfo(houseInfo.toString());
        receipt.setCommunityNo(receiptOrder.getCommunityNo());
        receipt.setCommunityName(receiptOrder.getCommunityName());
        receipt.setBatchPayOrderNo(receiptOrder.getChargeRecordId());
        receipt.setDepartmentNo(receiptOrder.getDepartmentNo());
        receipt.setDepartmentName(receiptOrder.getDepartmentName());
        receipt.setDepartmentNos(receiptOrder.getDepartmentNos());

        jdbcSession.insert(receipt);

        //文件上传成功后自动删除
        if (file.exists() && file.isFile() && file.delete() == true) {
            logger.info("{}本地文件已经删除!",pdfName);
        }

        //代表已经生成过了
        chargeBill.setFileId(fileId);

        return jdbcSession.updateById(chargeBill);
    }


    @Override
    public List<ReceiptsStatistics> groupData(JSONObject jsonObject, Token token) {
        //本月date1 ,上个月date2
        String date1;
        String date2;
        String strDate = jsonObject.getString("statistTime");
        if(null != strDate){
            date1 = strDate.substring(0,7);
            int num = Integer.parseInt(date1.substring(5,7))-1;
            date2 = date1.substring(0,5) + String.format("%02d", num);
        }else {
            //2.根据小区统计数据
            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR);
            int monthly = cal.get(Calendar.MONTH) + 1;
            int month = cal.get(Calendar.MONTH);
            //本月 (0 代表前面补充0,10代表长度为10,d 代表参数为正数型)
            date1 = year +"-"+ String.format("%02d", monthly);
            //上一个月 (0 代表前面补充0,10代表长度为10,d 代表参数为正数型)
            date2 = year +"-"+String.format("%02d", month);
        }
        JSONArray array = jsonObject.getJSONArray("communitys");
        QueryCondition query = Condition.createQuery(false);
        query.in("communityNo",array);
        query.groupBy("monthTime");
        query.groupBy("communityNo");
        List<ReceiptsStatistics> statistic = receiptOrdersDao.statistic(query);


        ReceiptsStatistics receipt;
        List<ReceiptsStatistics> statList = new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            String communityId = array.getString(i);
            receipt = new ReceiptsStatistics();
            //根据小区ID筛选结果集
            List<ReceiptsStatistics> listByCommunity = statistic.stream().filter(s -> communityId.equals(s.getCommunityName()))
                    .collect(Collectors.toList());
            //本月和上月数量
            int total = 0;
            Integer lastMonthNum = 0;
            Integer currentMonthlyNum = 0;
            if(!Objects.isEmpty(listByCommunity)){
                ReceiptsStatistics currentStatistics = listByCommunity.stream().filter(c -> c.getMonthTime().equals(date1)).findFirst().orElse(null);
                if(null != currentStatistics){
                    currentMonthlyNum = currentStatistics.getMonthlyNum();
                }
                ReceiptsStatistics lastStatistics = listByCommunity.stream().filter(c -> c.getMonthTime().equals(date2)).findFirst().orElse(null);
                if(null != lastStatistics){
                    lastMonthNum = lastStatistics.getMonthlyNum();
                }
                total = listByCommunity.stream().mapToInt(c->c.getMonthlyNum()).sum();
            }
            receipt.setCommunityName(communityId);
            receipt.setLastMonthNum(lastMonthNum);
            receipt.setMonthlyNum(currentMonthlyNum);
            receipt.setTotalNum(total);
            statList.add(receipt);
        }
        return statList;
    }




    private String getOwnerName(String companyNo, String houseNo) throws Exception{
        JSONObject result = doveClient.post("/basic/house/service/get", http->{
            http.addHeader("companyNo", companyNo);
            http.addParam("id", houseNo);
        });
        if (Objects.isNull(result) || Objects.isNull(result.getJSONObject("data"))) {
            return "";
        }
        JSONObject data = result.getJSONObject("data");
        return data.getString("ownerName");
    }


    @Override
    public Object update(ReceiptOrders receiptOrders) throws Exception {
        return jdbcSession.updateById(receiptOrders);
    }


    @Override
    public Object deleteById(String id) {
        ReceiptOrders result = Pool.get(ReceiptOrders.class, id);
        if (result != null) {
            result.setDeleted(true);
            jdbcSession.updateById(result);
        }
        return 1;
    }


}
